package maild

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

type (
	Message struct {
		index   int
		from    string
		date    string
		subject string
		msg     string
	}

	Mail struct {
		auth       *Auth
		pop3       *Pop3Client
		pop3Server string
		smtpServer string
		lasttime   time.Time
		msgs       []int
		sizes      []int
		mails      []Message
	}
)

func NewMail(host, port string) (mailServer *Mail, err error) {
	mailServer = &Mail{
		auth: &Auth{},
	}
	err = mailServer.SetPop3(host, port)
	return
}

func (m *Mail) SetAuth(username, password string) error {
	m.auth.SetUsername(username)
	m.auth.SetPassword(password)
	return m.pop3.Auth(m.auth.username, m.auth.password)
}

func (m *Mail) SetPop3Server(host, port string) {
	m.pop3Server = host + ":" + port
}

func (m *Mail) SetSmtpServer(host, port string) {
	m.smtpServer = host + ":" + port
}

func (m *Mail) SetPop3(host, port string) (err error) {
	m.SetPop3Server(host, port)
	if m.pop3 != nil {
		m.pop3.Quit()
	}
	m.pop3, err = Pop3DialTLS(m.pop3Server)
	return
}

func (m *Mail) Cmd(command string, args []string) error {

	switch command {
	case "check":
		return m.CheckMail()

	case "listall":
		return m.ListAll()

	case "show":
		index, err := strconv.Atoi(args[0])
		if err != nil {
			return err
		}
		return m.ShowMail(index)

	case "help":
		fmt.Println(`
check    check inbox
listall  list all unread mails
show     show mail
help     display this menu
exit     exit
quit     exit
`)
		break

	default:
		fmt.Println("invaild command")
	}
	return nil
}

func (m *Mail) CheckMail() (err error) {
	count, _, err := m.pop3.Stat()
	if err != nil {
		return
	}
	m.lasttime = time.Now()
	if count > 0 {
		fmt.Printf("%d mail unread.\n", count)
	}
	return
}

func (m *Mail) ListAll() (err error) {
	msgs, sizes, err := m.pop3.ListAll()
	if err != nil {
		return
	}
	m.lasttime = time.Now()
	m.msgs = msgs
	m.sizes = sizes
	if len(msgs) > 0 {
		for i := 0; i < len(msgs); i++ {
			fmt.Printf("[%d] size:%d\n", i, sizes[i])
		}
	}
	return
}

func (m *Mail) ShowMail(index int) (err error) {
	if len(m.msgs) > 0 {
		j := -1
		fmt.Println(m.msgs)
		for i := len(m.msgs) - 1; i >= 0; i-- {
			if m.msgs[i] == index {
				j = i
			}
		}
		if j == -1 {
			goto fail
		}
		j = -1
		for i := len(m.mails) - 1; i >= 0; i-- {
			if m.mails[i].index == index {
				j = i
				break
			}
		}
		if j == -1 {
			data, err := m.pop3.Retr(index)
			if err != nil {
				return err
			}
			lines := strings.Split(data, "\n")
			j = len(m.mails)
			m.mails = append(m.mails, Message{
				from:    lines[4],
				date:    lines[12],
				subject: lines[5],
				msg:     strings.Join(lines[16:], "\n"),
			})
		}
		fmt.Printf("%s\n%s\n%s\n\n%s\n\n",
			m.mails[j].from,
			m.mails[j].date,
			m.mails[j].subject,
			m.mails[j].msg)
		return nil
	}
fail:
	fmt.Printf("index:%d not found\n", index)
	return
}
